package registry

import (
	"encoding/json"
	"path"
	"sync"
	"time"
	"wf-deploy-agent/conf"
	"wf-deploy-agent/infra"
	entity "wf-deploy-agent/registry/entity"
	"wf-deploy-agent/util"
)

type Repository struct {
	reg Registry
	dis Discovery
}

var repo *Repository
var mutex sync.Mutex

func GetRepository() *Repository {
	if repo != nil {
		return repo
	}

	mutex.Lock()
	repo = &Repository{
		dis: dis,
		reg: reg,
	}
	mutex.Unlock()

	return repo
}

// registerService 注册仓储服务节点
func (r *Repository) registerService(batchNO string) {
	err := r.reg.Register(conf.CF.Agent.Repository.Name+"-"+batchNO, []byte(""), 0)
	if err != nil {
		infra.Logger.Errorln(err)
	}
}

// registerInstance 注册仓储实例节点
func (r *Repository) registerInstance(batchNO string) {
	key := util.GetMD5(conf.CF.Agent.Identity)
	service := conf.CF.Agent.Repository.Name + "-" + batchNO
	instance := entity.ServiceRegistration{
		Id:                  key,
		Name:                service,
		Address:             util.GetLocalIp(),
		Port:                conf.CF.Agent.Service.Port,
		SslPort:             nil,
		RegistrationTimeUTC: time.Now().UnixMilli(),
		ServiceType:         "DYNAMIC",
		Payload: map[string]any{
			//@class为了兼容spring-cloud-starter-zookeeper-discovery
			"@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
			"id":     conf.CF.Agent.Service.Name,
			"name":   conf.CF.Agent.Service.Name,
			"metadata": map[string]any{
				"instance_status": "up",
			},
		},
		UriSpec: map[string]any{
			"parts": []map[string]any{
				{
					"value":    "scheme",
					"variable": true,
				},
				{
					"value":    "://",
					"variable": false,
				},
				{
					"value":    "address",
					"variable": true,
				}, {
					"value":    ":",
					"variable": false,
				}, {
					"value":    "port",
					"variable": true,
				},
			},
		},
	}

	bytes, err := json.Marshal(&instance)
	if err != nil {
		infra.Logger.Errorln(err)
		return
	}

	node := path.Join(service, key)
	err = r.reg.Register(node, bytes)
	if err != nil {
		infra.Logger.Fatalln(err)
	}
}

// Register 注册仓储服务
func (r *Repository) Register(batchNO string) {
	r.registerService(batchNO)
	r.registerInstance(batchNO)
}

// GetService 获取指定的仓储服务
func (r *Repository) GetService(batchNO string) []*entity.ServiceInstance {
	service := conf.CF.Agent.Repository.Name + "-" + batchNO
	instance, err := r.dis.GetService(service)
	if err != nil {
		infra.Logger.Errorln(err)
		return []*entity.ServiceInstance{}
	}

	return instance
}

// GetInstance 获取一个可用的仓储服务实例
func (r *Repository) GetInstance(batchNO string) *entity.ServiceInstance {
	service := conf.CF.Agent.Repository.Name + "-" + batchNO
	instances, err := r.dis.GetService(service)
	if err != nil {
		return nil
	}

	others := make([]*entity.ServiceInstance, 0)
	for _, instance := range instances {
		if instance.GetHostName() != conf.GetInstanceHost() {
			others = append(others, instance)
		}
	}

	if len(others) == 0 {
		return nil
	}

	now := time.Now().Unix()
	i := int(now) % len(others)
	instance := others[i]

	return instance
}
